#|______________________________________________________________________________
 |
 | plots004.lsp
 |
 | Contains the following constructor functions for the new ViSta Plots System:
 |
 |   box-or-diamond-plot 
 |   parallel-coordinates-plot 
 |   grouped-box-plot
 |   diamond-plot
 |   box-plot
 |______________________________________________________________________________
 |#

(defun box-or-diamond-plot 
  (&optional data &key (ok-var-types '(numeric)) 
             variable-labels point-labels 
             (show t) (top-most t) (linked t) (connect nil)
             (location '(50 50)) (size '(320 320))
             (title "Box or Diamond Plot") 
             (legend1 "Unnamed Data") (legend2 nil)
             ;following dont work
             (content-only nil)  (go-away t)
             ;do not use menu-item, menu, in, in?, in??, or in???
             ;all are reserved for system use 
             (menu-item nil) (menu t)
             (in nil in??) (in? nil in???)
             ;following are unique to this plot
             (y-axis-label "Data") 
             (x-axis-label " ") 
             (category nil)
             (parallel-coordinates nil)
             (boxes t) 
             (diamonds nil) 
             (median-line nil) 
             (mean-line nil)        
             (equate t) 
             (enable-equate t)
             (jitter t)
             (connect-points t) 
             (enable-connect-points t)
             (toolbar nil)
             )
"The Box, Diamond and Dot plot uses boxes, diamonds and dots to form a schematic of a set of observations. The schematic can give you insight into the shape of the distribution of observations. Some Box, Diamond and Dot plots have several schematics. These side-by-side plots can also help you see if the distributions have the same average value and the same variation in values. 

Args: &optional data &key (ok-var-types '(numeric)) (title nil) (in nil) (show t) variable-labels point-labels (legend1 (send $ :name)) (legend2 nil) (location '(50 50)) (size '(nil 250)) (go-away t) (content-only nil) (help-bar nil) (pop-up t) (y-axis-label \"Data\") (x-axis-label \" \") (category nil) (boxes t) (diamonds nil) (median-line t) (mean-line nil) (equate t) (enable-equate t) (jitter t) (connect-points t) (enable-connect-points t) (nvar nil)
DATA may be nil, an object, a list of lists, a list of vectors, or a matrix. If not specified, DATA is assumed to be and is converted to a list of vectors, one vector for each of the OK-VAR-TYPES variables in the current-data. Plot is of the first few vectors in the list of vectors, the number of vectors depending on the details of the plot unless specified. The plot is prepared to appear but not shown if SHOW is NIL. It appears on the desktop when IN is not specified; in IN when IN is specified to be a container; in the XLispStat window if IN is specified as NIL; or in  *active-container* if IN is specified as T and *active-container*  is a container window (desktop, if *active-container* is not a container window). The plot will include variable-labels, point-labels and legends, as specified. The plot will have a close box which will be de-activated when GO-AWAY is T. When CONTENT-ONLY is T the button bars, legends and overlays do not appear. When HELP-BAR is NIL the help-bar does not appear. When POP-UP is NIL the pop-up menus are not available. 
    Makes one or many dot plots, with optional boxplots and/or diamondplots superimposed.  Dots are jittered unless JITTER is nil. Points in parallel plots may be connected if each plot has the same number of observations. Parallel plots may also be connected with mean or median line.   Boxplots are based on the five number summary.  Diamond plots are based on the mean and standard deviation.  Widths of boxes and diamonds are proportional to number of observations in the sequence. Categoried side-by-side box/diamonds plots are made of a single variable classified into the categories of a category variable when CATEGORY is T.
    The BOXES, DIAMONDS, MEAN-LINE and MEDIAN-LINE  arguments determine which features are initially displayed.  Default is that only boxes are displayed. ENABLE-CONNECT-POINTS displays the connect box and enables point connections, the points being initially connected if CONNECT-POINTS is also true (only appropriate for multivariate data). ENABLE-EQUATE displays equate box and, if EQUATE is also T normalizes all variables onto comparable scales. Written by Forrest W. Young"
  (let* ((actcon *active-container*)
         (in? (if in??? in? in??))
         (graph-frame (graph-frame :show nil))
         (pop-out (send graph-frame :seen-in in in?))
         (container (if (equal pop-out t) graph-frame pop-out))
         (graph-data (before-new-plot data ok-var-types))
         (data-object (fourth graph-data))
         (linkable t)
         (graph))
    (unless variable-labels (setf variable-labels (second graph-data)))
    (unless point-labels (setf point-labels (third graph-data)))
    (setf graph-data (first graph-data))
    (when (not (first size))
          (setf size (list (min (first (- (screen-size) 100))
                                (* (max 3 (length variable-labels)) 80))
                           (second size))))
    (unless title 
            (setf title (if (> (length graph-data) 1) 
                            "Side-By-Side Box Plots" 
                            "Box Plot")))
    (unless legend2 (setf legend2 title))
    (setf graph
          (send boxplot-proto :new graph-data                        
                :variable-labels variable-labels :point-labels point-labels
                :show nil                        :top-most top-most
                :container container             :pop-out pop-out
                :actcon actcon                   
                :location location               :size size 
                :menu menu                       :title title 
                :legend1 legend1                 :legend2 legend2
                :go-away go-away                 :content-only content-only
                ;MODULE-SPECIFIC ARGUMENTS
                :boxes boxes                     :diamonds diamonds 
                :parallel-coordinates parallel-coordinates 
                :median-line median-line         :mean-line mean-line
                :enable-connect-points enable-connect-points 
                :connect-points connect-points   :jitter jitter
                :enable-equate enable-equate     :equate equate
                :y-axis-label y-axis-label       :x-axis-label x-axis-label))
    (when graph
          (send graph :legend1 
                (if data-object (send data-object :name)
                    "Unnamed Data"))
          (send graph :title (strcat title " [" (send graph :legend1) "]"))
          (send graph :make-two-plot-menus
                "BoxPlot"
                :hotspot-items '(help dash link dash
                                 show-plots hide-plots close-plots dash 
                                 print save copy dash on-top maximize)
                :popup-items   '(showing-labels mouse resize-brush dash 
                                 select-all unselect-all show-all dash 
                                 erase-selection focus-on-selection view-selection dash
                                 color symbol dash selection slicer))
          (send graph :mouse-mode 'brushing)
          (send graph :connect-points connect-points) 
          (when parallel-coordinates 
                (send graph :point-symbol (iseq (send graph :num-points)) 'dot)
                (send graph :adjust-points (iseq (send graph :num-points)) 'hilited))
          (when parallel-coordinates
                (send graph :delete-overlay (first (send graph :overlays)))
                (send graph :margin 0 20 30 5))
          (send graph :after-new-plot 
                pop-out top-most show '(320 320) container linkable linked
                data-object content-only)
          
          )
    graph))

(defun parallel-coordinates 
  (&optional data &key (title "Parallel Coordinates Plot") location (size '(320 320))
             variable-labels point-labels (go-away t) (show t) 
             (legend1 "Unnamed Data") (legend2 nil)
             (in nil in?) (content-only nil) (plot-type "pc-plot")
             (y-axis-label "Data") (x-axis-label "Variables") (category nil))
  (let ((pcp (box-or-diamond-plot 
              data :ok-var-types '(numeric) 
              :title "Parallel Coordinates Plot" 
              :in in :in? in? :show show 
              :variable-labels variable-labels :point-labels point-labels 
              :legend1 legend1 :legend2 legend2 
              :location location :size size 
              :go-away go-away :content-only content-only 
              :y-axis-label y-axis-label :x-axis-label x-axis-label 
              :category nil :boxes nil :diamonds nil 
              :median-line nil :mean-line nil 
              :equate t :enable-equate t :jitter nil 
              :connect-points t :enable-connect-points t 
              :jitter nil :parallel-coordinates t)))
    pcp))


(defun grouped-box-plot 
  (&optional data &key (ok-var-types '(numeric category))
             variable-labels point-labels 
             (show t) (top-most t) (linked t) (connect nil)
             (location '(50 50)) (size '(320 320))
             (title "Grouped Box Plot") 
             (legend1 "Unnamed Data") (legend2 nil)
             (content-only nil)  (go-away t)
             ;do not use :in?, :in??, or :in??? - reserved for system use
             (in nil in??) (in? nil in???)
             ;unique keywords for this plot
             (jitter t) (boxes t) diamonds 
             equate median-line mean-line)
"Args:  data
        &key (ok-var-types '(numeric category))
             variable-labels point-labels 
             (show t) (top-most t) (linked t) (connect nil)
             (location '(50 50)) (size '(320 320))
             (title \"Grouped Box Plot\") 
             (legend1 (send current-object :name))  (legend2 \" \")
             (content-only nil)  (go-away t)
             (jitter t) (boxes t) diamonds 
             equate median-line mean-line)
DATA is nil or an object. May not be a sequence, a list of sequences or a matrix. Defaults to the first active numeric and category variables in the current-data if not specified. Makes categorized boxplot, diamond or dot plots, there being a plot for every category of CATEGORY variable, the plot being of all observations of NUMERIC VARIABLE that fall in the category of CATEGORY VARIABLE.  Dots are jittered unless JITTER is nil. Boxplots are based on the five number summary.  Diamond plots are based on the mean and standard deviation.  Widths of boxes and diamonds are proportional to number of observations in the sequence. The BOXES, DIAMONDS, MEAN-LINE and MEDIAN-LINE arguments determine which features are initially displayed.  Default is that only boxes are displayed. CONNECT-POINTS must be true to enable point connections (only appropriate for multivariate data). Points not jittered when connected. EQUATE displays equate box and normalizes all variables onto comparable scales."
  (let* ((actcon *active-container*)
         (in? (if in??? in? in??))
         (graph-frame (graph-frame :show nil))
         (pop-out (send graph-frame :seen-in in in?))
         (connect-only connect)
         (container (if (equal pop-out t) graph-frame pop-out))
         (graph-data (before-new-plot data ok-var-types))
         (data-object (fourth graph-data))
         (variable-types (fifth graph-data))
         (cat-var-pstns (which (mapcar #'(lambda (element)
                                           (equal (string-downcase element) "category"))
                                       (fifth graph-data))))
         (num-var-pstns (which (mapcar #'(lambda (element)
                                           (equal (string-downcase element) "numeric"))
                                       (fifth graph-data))))
         (variable-labels (if variable-labels variable-labels (second graph-data)))
         (point-labels (if point-labels point-labels (third graph-data)))
         (category-labels
          (coerce  
           (remove-duplicates 
            (select (first graph-data) (first cat-var-pstns)) :test #'equal) 'list))
         (numeric-variable 
          (coerce (select (first graph-data) (first num-var-pstns)) 'list))
         (category-variable 
          (coerce (select (first graph-data) (first cat-var-pstns)) 'list))
         (grouped-data (categorize-numeric-variable numeric-variable category-variable))
         ;PV boxplots are sorted according to the medians
         (order (order (mapcar 'median grouped-data)));pv
         (grouped-data (select grouped-data order));PV
         (original-order (combine (select (categorize-numeric-variable 
                                           (iseq (length numeric-variable))
                                           category-variable) order)));PV
         (linkable t)
         (graph)
         )
    (when (not (first size))
          (setf size (list (min (first (- (screen-size) 100))
                                (* (max 3 (length variable-labels)) 80))
                           (second size))))
    
    (unless legend2 (setf legend2 title))
    (setf graph
          (send boxplot-proto :new grouped-data :title title :point-labels point-labels
                :variable-labels category-labels :location location :boxes boxes
                :diamonds diamonds :median-line median-line :mean-line mean-line
                :enable-connect-points nil :enable-equate equate :grouped t
                :box-button t :diamond-button t :median-line-button nil 
                :mean-line-button nil :equate-button t :connect-points-button nil 
                :jitter jitter :size size :go-away go-away :show nil
                :content-only content-only
                :x-axis-label (if variable-labels (first variable-labels) "Groups")
                :y-axis-label (if variable-labels (second variable-labels) " ")
                ;PV added original-order
                :legend1 legend1 :legend2 legend2 :original-order original-order)) 
    (when graph
          (send graph :legend1 
                (if data-object (send data-object :name)
                    "Unnamed Data"))
          (send graph :title (strcat title " [" (send graph :legend1) "]"))
          (send graph :make-two-plot-menus
                "CatBoxPlot"
                :hotspot-items '(help dash link dash
                                 show-plots hide-plots close-plots dash 
                                 print save copy dash on-top maximize)
                :popup-items   '(showing-labels mouse resize-brush dash 
                                 select-all unselect-all show-all dash 
                                 erase-selection focus-on-selection view-selection dash
                                 color symbol dash selection slicer))
          (send graph :mouse-mode 'brushing)
          (send graph :delete-overlay (first (send graph :overlays)))
          (send graph :margin 0 20 30 0)
          (send graph :after-new-plot
                pop-out top-most show size container linkable linked
                data-object content-only))
    graph))

(defun pc-plot (&rest args) (apply #'parallel-coordinates-plot args))

(defun diamond-plot (&optional data &key (title "Diamond Plot") location (size '(300 300))
                           variable-labels point-labels (go-away t) (show t)
                           (legend1 "Unnamed Data") (legend2 nil)
                           (in nil in?) (content-only nil)
                           (y-axis-label "Data") (x-axis-label " ") (category nil)
                           (boxes nil) (diamonds t) (median-line nil) (mean-line t) 
                           (equate t) (connect-points t) (content-only nil) (jitter t) 
                           )
"Args: ((&optional data &key (title \"Diamond Plot\") location size
                           variable-labels point-labels (go-away t) (show t)
                           (legend1 (send current-object :name))  (legend2 \" \")

                           (y-axis-label \"Data\") (x-axis-label \" \") (category nil)
                           (boxes nil) (diamonds t) (median-line nil) (mean-line t) 
                           (equate t) (connect-points t) (content-only nil) (jitter t)
DATA is nil or an object, a sequence, a list of sequences or a matrix. Defaults to the active numeric variables in the current-data if not specified. Plot is of the sequence or sequences in the list or the columns of the matrix. Makes one or many parallel dot plots, with optional boxplots and/or diamondplots superimposed.  Dots are jittered unless JITTER is nil. Points in parallel plots may be connected if each plot has the same number of observations. Parallel plots may also be connected with mean or median line.   Boxplots are based on the five number summary.  Diamond plots are based on the mean and standard deviation.  Widths of boxes and diamonds are proportional to number of observations in the sequence. The BOXES, DIAMONDS, MEAN-LINE and MEDIAN-LINE  arguments determine which features are initially displayed.  Default is that only boxes are displayed. CONNECT-POINTS must be true to enable point connections (only appropriate for multivariate data). Points not jittered when connected. EQUATE displays equate box and normalizes all variables onto comparable scales. The arguments ending with -BUTTON determine which buttons will be on the toolbar. Plot appears in the active container, if there is one, or on the desktop when there is none."
  (box-or-diamond-plot data :ok-var-types '(numeric) :title "Diamond Plot" :in in :in? in? :show show :variable-labels variable-labels :point-labels point-labels :legend1 legend1 :legend2 legend2 :location location :size size :go-away go-away :content-only content-only :help-bar nil :pop-up t :y-axis-label y-axis-label :x-axis-label x-axis-label :category nil :boxes nil :diamonds t :median-line nil :mean-line nil :equate t :enable-equate t :jitter t :connect-points t :enable-connect-points t))


(defun box-plot (&optional data &key (title "Box Plot") location (size '(300 300))
                           variable-labels point-labels (go-away t) (show t)
                          (legend1 "Unnamed Data") (legend2 nil)
                           (in nil in?) (content-only nil)
                           (y-axis-label "Data") (x-axis-label " ") (category nil)
                           (boxes nil) (diamonds t) (median-line nil) (mean-line t) 
                           (equate t) (connect-points t) (content-only nil) (jitter t) 
                           )
"Args: ((&optional data &key (title \"Box Plot\") location size
                           variable-labels point-labels (go-away t) (show t)
                           (legend1 \"Unnamed Data\")  (legend2 \" \")

                           (y-axis-label \"Data\") (x-axis-label \" \") (category nil)
                           (boxes nil) (diamonds t) (median-line nil) (mean-line t) 
                           (equate t) (connect-points t) (content-only nil) (jitter t)
DATA is nil or an object, a sequence, a list of sequences or a matrix. Defaults to the active numeric variables in the current-data if not specified. Plot is of the sequence or sequences in the list or the columns of the matrix. Makes one or many parallel dot plots, with optional boxplots and/or diamondplots superimposed.  Dots are jittered unless JITTER is nil. Points in parallel plots may be connected if each plot has the same number of observations. Parallel plots may also be connected with mean or median line.   Boxplots are based on the five number summary.  Diamond plots are based on the mean and standard deviation.  Widths of boxes and diamonds are proportional to number of observations in the sequence. The BOXES, DIAMONDS, MEAN-LINE and MEDIAN-LINE  arguments determine which features are initially displayed.  Default is that only boxes are displayed. CONNECT-POINTS must be true to enable point connections (only appropriate for multivariate data). Points not jittered when connected. EQUATE displays equate box and normalizes all variables onto comparable scales. The arguments ending with -BUTTON determine which buttons will be on the toolbar. Plot appears in the active container, if there is one, or on the desktop when there is none."
  (box-or-diamond-plot data :ok-var-types '(numeric) 
                       :title "Box Plot" 
                       :in in :in? in? :show show 
                       :variable-labels variable-labels 
                       :point-labels point-labels 
                       :legend1 legend1 :legend2 legend2 
                       :location location :size size 
                       :go-away go-away :content-only content-only 
                       :help-bar nil :pop-up t 
                       :y-axis-label y-axis-label 
                       :x-axis-label x-axis-label 
                       :category nil  :jitter t 
                       :boxes t :diamonds nil 
                       :median-line nil :mean-line nil 
                       :equate t :enable-equate t 
                       :connect-points t :enable-connect-points t))


